// Copyright (C) Calum Grant 2008

namespace dynamic
{
	/// Contains code not for public use.
	namespace internal
	{
		DYNAMIC_API void *apartment_malloc(std::size_t bytes);
		DYNAMIC_API void apartment_free(void *p);

		/// Use to temporarily release an apartment (for a wait operation etc).
		/** \ingroup  mem */
		class DYNAMIC_API leave_apartment : cg::not_copyable, cg::not_assignable
		{
		public:
			leave_apartment();
			~leave_apartment();
		private:
			leave_apartment(const leave_apartment&);
			leave_apartment & operator=(const leave_apartment&);
		};


		/// Creates a new \ref apartment and sets the current apartment to be the new apartment.
		/** \ingroup mem */
		class DYNAMIC_API use_new_apartment : cg::not_copyable, cg::not_assignable
		{
		public:
			use_new_apartment();
			~use_new_apartment();
		private:
			apartment * m_previous;
		};
	}


	/// Implements a Kingsley allocator.
	/** \ingroup  mem 
		\see test_heap() */
	class DYNAMIC_API kingsley_heap
	{
	public:
		kingsley_heap();
		~kingsley_heap();
		void * malloc(std::size_t bytes);
		void free(void * p);
		void defrag();

	private:
		static const int num_blocks = 32;
		void **m_blocks[num_blocks];
		void ** m_allocated;
	};


	/// An allocator which allocates memory in the local heap.
	/** \ingroup  mem */
	template<typename T>
	struct allocator : public std::allocator<T>	// ??
	{
		typedef std::size_t size_type;
		typedef std::ptrdiff_t difference_type;
		typedef T * pointer;
		typedef const T * const_pointer;
		typedef T & reference;
		typedef const T & const_reference;
		typedef T value_type;
		template<typename U> struct rebind { typedef allocator<U> other; };
		// size_type max_size() const { return -1; }

		allocator() throw() { }
		allocator(const allocator&) throw() { }
		template<typename U> allocator(const allocator<U>&) throw() { }
		~allocator() throw() { }

		pointer address(reference x) { return &x; }
		const_pointer address(const_reference x) { return &x; }

		pointer allocate(size_type s, void* = 0)
		{
			return (pointer)internal::apartment_malloc(s * sizeof(T));
		}

		void deallocate(pointer p, size_type)
		{
			internal::apartment_free(p);
		}

		void construct(pointer p, const_reference val) { new(p) T(val); }
		void destroy(pointer p) { p->~T(); }
	};
}

